/*
 * Copyright 2009 XueSong Guo.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.webwheel.database.engine;

import cn.webwheel.database.SqlObject;
import cn.webwheel.database.types.AsciiStream;
import cn.webwheel.database.types.BinaryStream;
import cn.webwheel.database.types.CharacterStream;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

class Utils {
    static int getBasicResult(Class type, StringBuilder body, String idx, String var) {
        try {
            Integer.parseInt(idx);
        } catch (NumberFormatException e) {
            if(idx!=null) idx = '"' + idx + '"';
        }
        if (type == java.sql.Array.class) {
            if (body == null) return 3;
            body.append(var + " = _rs.getArray(" + idx + ");");
        } else if (type == AsciiStream.class) {
            if (body == null) return 3;
            body.append(var + " = " + AsciiStream.class.getName() + ".valueOf(_rs.getAsciiStream(" + idx + "));");
        } else if (type == java.math.BigDecimal.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getBigDecimal(" + idx + ");");
        } else if (type == BinaryStream.class) {
            if (body == null) return 3;
            body.append(var + " = " + BinaryStream.class.getName() + ".valueOf(_rs.getBinaryStream(" + idx + "));");
        } else if (type == java.sql.Blob.class) {
            if (body == null) return 3;
            body.append(var + " = " + Blob.class.getName() + ".valueOf(_rs.getBlob(" + idx + "));");
        } else if (type == boolean.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getBoolean(" + idx + ");");
        } else if (type == Boolean.class) {
            if (body == null) return 1;
            body.append(var + " = Boolean.valueOf(_rs.getBoolean(" + idx + "));");
            body.append("if(_rs.wasNull()) " + var + " = null;");
        } else if (type == byte.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getByte(" + idx + ");");
        } else if (type == Byte.class) {
            if (body == null) return 1;
            body.append(var + " = Byte.valueOf(_rs.getByte(" + idx + "));");
            body.append("if(_rs.wasNull()) " + var + " = null;");
        } else if (type == byte[].class) {
            if (body == null) return 3;
            body.append(var + " = _rs.getBytes(" + idx + ");");
        } else if (type == CharacterStream.class) {
            if (body == null) return 3;
            body.append(var + " = " + CharacterStream.class.getName() + ".valueOf(_rs.getCharacterStream(" + idx + "));");
        } else if (type == java.sql.Clob.class) {
            if (body == null) return 3;
            body.append(var + " = " + Clob.class.getName() + ".valueOf(_rs.getClob(" + idx + "));");
        } else if (type == java.sql.Date.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getDate(" + idx + ");");
        } else if (type == double.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getDouble(" + idx + ");");
        } else if (type == Double.class) {
            if (body == null) return 1;
            body.append(var + " = Double.valueOf(_rs.getDouble(" + idx + "));");
            body.append("if(_rs.wasNull()) " + var + " = null;");
        } else if (type == float.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getFloat(" + idx + ");");
        } else if (type == Float.class) {
            if (body == null) return 1;
            body.append(var + " = Float.valueOf(_rs.getFloat(" + idx + "));");
            body.append("if(_rs.wasNull()) " + var + " = null;");
        } else if (type == int.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getInt(" + idx + ");");
        } else if (type == Integer.class) {
            if (body == null) return 1;
            body.append(var + " = Integer.valueOf(_rs.getInt(" + idx + "));");
            body.append("if(_rs.wasNull()) " + var + " = null;");
        } else if (type == long.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getLong(" + idx + ");");
        } else if (type == Long.class) {
            if (body == null) return 1;
            body.append(var + " = Long.valueOf(_rs.getLong(" + idx + "));");
            body.append("if(_rs.wasNull()) " + var + " = null;");
        } else if (type == java.sql.Ref.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getRef(" + idx + ");");
        } else if (type == short.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getShort(" + idx + ");");
        } else if (type == Short.class) {
            if (body == null) return 1;
            body.append(var + " = Short.valueOf(_rs.getShort(" + idx + "));");
            body.append("if(_rs.wasNull()) " + var + " = null;");
        } else if (type == String.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getString(" + idx + ");");
        } else if (type == java.sql.Time.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getTime(" + idx + ");");
        } else if (type == java.sql.Timestamp.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getTimestamp(" + idx + ");");
        } else if (type == java.net.URL.class) {
            if (body == null) return 1;
            body.append(var + " = _rs.getURL(" + idx + ");");
        } else if(SqlObject.class.isAssignableFrom(type)) {
            if (body == null) return 3;
            body.append(var + " = (" + type.getCanonicalName() + ")" + SqlObjectHandler.class.getName() + ".get(_rs, " + idx + ");");
        } else {
            return 2;
        }
        return -1;
    }

    static boolean isBasicType(Class type) {
        return (getBasicResult(type, null, null, null)&1)!=0;
    }

    static boolean isIgnoreDef(Class type) {
        return (getBasicResult(type, null, null, null)&2)!=0;
    }

    public static boolean setStmtParam(Class type, StringBuilder body, int idx, String exp) {
        if (type == java.sql.Array.class) {
            body.append("_stmt.setArray(" + idx + ", " + exp + ");");
        } else if (type == AsciiStream.class) {
            body.append("_stmt.setAsciiStream(" + idx + ", " + exp + ");");
        } else if (type == java.math.BigDecimal.class) {
            body.append("_stmt.setBigDecimal(" + idx + ", " + exp + ");");
        } else if (type == BinaryStream.class) {
            body.append("_stmt.setBinaryStream(" + idx + ", " + exp + ");");
        } else if (type == java.sql.Blob.class) {
            body.append("_stmt.setBlob(" + idx + ", " + exp + ");");
        } else if (type == boolean.class) {
            body.append("_stmt.setBoolean(" + idx + ", " + exp + ");");
        } else if (type == Boolean.class) {
            body.append("_stmt.setObject(" + idx + ", " + exp + ", java.sql.Types.BOOLEAN);");
        } else if (type == byte.class) {
            body.append("_stmt.setByte(" + idx + ", " + exp + ");");
        } else if (type == Byte.class) {
            body.append("_stmt.setObject(" + idx + ", " + exp + ", java.sql.Types.TINYINT);");
        } else if (type == byte[].class) {
            body.append("_stmt.setBytes(" + idx + ", " + exp + ");");
        } else if (type == CharacterStream.class) {
            body.append("_stmt.setCharacterStream(" + idx + ", " + exp + ");");
        } else if (type == java.sql.Clob.class) {
            body.append("_stmt.setClob(" + idx + ", " + exp + ");");
        } else if (type == java.sql.Date.class) {
            body.append("_stmt.setDate(" + idx + ", " + exp + ");");
        } else if (type == double.class) {
            body.append("_stmt.setDouble(" + idx + ", " + exp + ");");
        } else if (type == Double.class) {
            body.append("_stmt.setObject(" + idx + ", " + exp + ", java.sql.Types.DOUBLE);");
        } else if (type == float.class) {
            body.append("_stmt.setFloat(" + idx + ", " + exp + ");");
        } else if (type == Float.class) {
            body.append("_stmt.setObject(" + idx + ", " + exp + ", java.sql.Types.FLOAT);");
        } else if (type == int.class) {
            body.append("_stmt.setInt(" + idx + ", " + exp + ");");
        } else if (type == Integer.class) {
            body.append("_stmt.setObject(" + idx + ", " + exp + ", java.sql.Types.INTEGER);");
        } else if (type == long.class) {
            body.append("_stmt.setLong(" + idx + ", " + exp + ");");
        } else if (type == Long.class) {
            body.append("_stmt.setObject(" + idx + ", " + exp + ", java.sql.Types.BIGINT);");
        } else if (type == java.sql.Ref.class) {
            body.append("_stmt.setRef(" + idx + ", " + exp + ");");
        } else if (type == short.class) {
            body.append("_stmt.setShort(" + idx + ", " + exp + ");");
        } else if (type == Short.class) {
            body.append("_stmt.setObject(" + idx + ", " + exp + ", java.sql.Types.SMALLINT);");
        } else if (type == String.class) {
            body.append("_stmt.setString(" + idx + ", " + exp + ");");
        } else if (type == java.sql.Time.class) {
            body.append("_stmt.setTime(" + idx + ", " + exp + ");");
        } else if (type == java.sql.Timestamp.class) {
            body.append("_stmt.setTimestamp(" + idx + ", " + exp + ");");
        } else if (type == java.net.URL.class) {
            body.append("_stmt.setURL(" + idx + ", " + exp + ");");
        } else if (SqlObject.class.isAssignableFrom(type)) {
            body.append(SqlObjectHandler.class.getName() + ".set(_stmt, " + idx + ", " + exp + ");");
        } else {
            return false;
        }
        return true;
    }

    public static Class<?> getListSetterComType(Method method) {
        Type type = method.getGenericParameterTypes()[0];
        if (type instanceof ParameterizedType) {
            return (Class<?>) ((ParameterizedType)type).getActualTypeArguments()[0];
        } else {
            return null;
        }
    }

    public static String getSetterPropName(Method method) {
        String s = method.getName().substring(3);
        return s.substring(0, 1).toLowerCase() + s.substring(1);
    }

    public static String strSrc(String s) {
        return s.replace("\\", "\\\\").replace("\n", "\\n").replace("\r", "\\r").replace("\"", "\\\"");
    }
}